import {
  type ColumnDef,
  type ColumnFiltersState,
  flexRender,
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  type PaginationState,
  useReactTable,
} from "@tanstack/react-table";
import {
  ChevronFirstIcon,
  ChevronLastIcon,
  ChevronLeftIcon,
  ChevronRightIcon,
} from "lucide-react";
import * as React from "react";
import { Drawer, DrawerTrigger } from "@/components/ui/drawer";
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectLabel,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { useScreenSize } from "@/hooks/use-screen";
import { Button } from "../ui/button";
import { Input } from "../ui/input";
import type { Issue } from "./issues-columns";
import { IssuesDatePicker } from "./issues-date-picker";
import { IssuesItem } from "./issues-item";

interface DataTableProps<TData, TValue> {
  columns: ColumnDef<TData, TValue>[];
  data: TData[];
}

export function IssuesTable<TData, TValue>({
  columns,
  data,
}: DataTableProps<TData, TValue>) {
  const { screenSize } = useScreenSize();
  const [rows, setRows] = React.useState(15);
  const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
    [],
  );
  const [pagination, setPagination] = React.useState<PaginationState>({
    pageIndex: 0,
    pageSize: rows,
  });
  const tableContainerRef = React.useRef<HTMLDivElement>(null);
  const [rowHeight, setRowHeight] = React.useState<number>(36);

  React.useEffect(() => {
    switch (screenSize) {
      case "2xl":
        setRows(20);
        break;
      default:
        setRows(15);
    }
  }, [screenSize]);

  React.useEffect(() => {
    setPagination((prev) => ({
      ...prev,
      pageSize: rows,
    }));
  }, [rows]);

  React.useEffect(() => {
    const calculateRowHeight = () => {
      if (tableContainerRef.current) {
        const containerHeight = tableContainerRef.current.clientHeight;
        const availableHeight = containerHeight - 36;
        const calculatedHeight = Math.max(
          32,
          Math.min(availableHeight / rows, 100),
        );
        setRowHeight(calculatedHeight);
      }
    };

    calculateRowHeight();

    window.addEventListener("resize", calculateRowHeight);

    const resizeTimer = setTimeout(calculateRowHeight, 100);

    return () => {
      window.removeEventListener("resize", calculateRowHeight);
      clearTimeout(resizeTimer);
    };
  }, [rows]);

  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
    onColumnFiltersChange: setColumnFilters,
    getFilteredRowModel: getFilteredRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    onPaginationChange: setPagination,
    state: {
      columnFilters,
      pagination,
    },
  });

  return (
    <div className="flex h-full w-full flex-col gap-4">
      <div className="grid grid-cols-6 gap-4">
        <Input
          placeholder="Filter by title"
          value={(table.getColumn("title")?.getFilterValue() as string) ?? ""}
          onChange={(event) =>
            table.getColumn("title")?.setFilterValue(event.target.value)
          }
          className="w-full border-border"
        />
        <Input
          placeholder="Filter by test"
          value={(table.getColumn("test")?.getFilterValue() as string) ?? ""}
          onChange={(event) =>
            table.getColumn("test")?.setFilterValue(event.target.value)
          }
          className="w-full border-border"
        />
        <Select
          onValueChange={(value) =>
            table
              .getColumn("type")
              ?.setFilterValue(value === "all" ? undefined : value)
          }
        >
          <SelectTrigger className="w-full border-border">
            <SelectValue placeholder="Filter by types" />
          </SelectTrigger>
          <SelectContent>
            <SelectGroup>
              <SelectLabel>Types</SelectLabel>
              <SelectItem value="all">all</SelectItem>
              <SelectItem value="bug">bug</SelectItem>
              <SelectItem value="script">script</SelectItem>
              <SelectItem value="env">env</SelectItem>
            </SelectGroup>
          </SelectContent>
        </Select>
        <Select
          onValueChange={(value) =>
            table
              .getColumn("owner")
              ?.setFilterValue(value === "all" ? undefined : value)
          }
        >
          <SelectTrigger className="w-full border-border">
            <SelectValue placeholder="Filter by owner" />
          </SelectTrigger>
          <SelectContent>
            <SelectGroup>
              <SelectLabel>Owners</SelectLabel>
              <SelectItem value="all">All</SelectItem>
              <SelectItem value="Rudy Lang">Rudy Lang</SelectItem>
            </SelectGroup>
          </SelectContent>
        </Select>
        <div className="col-start-6">
          <IssuesDatePicker />
        </div>
      </div>
      <div className="flex h-full flex-col items-center gap-4">
        <div ref={tableContainerRef} className="h-full w-full border bg-card">
          <Table className="border-collapse [&_td:not(:last-child)]:border-r [&_td]:border-border [&_th:not(:last-child)]:border-r">
            <TableHeader className="sticky top-0 z-10 border-b bg-background">
              {table.getHeaderGroups().map((headerGroup) => (
                <TableRow
                  key={headerGroup.id}
                  className="border-border border-b hover:bg-transparent"
                >
                  {headerGroup.headers.map((header) => {
                    return (
                      <TableHead
                        key={header.id}
                        className="h-9"
                        style={{ width: header.getSize() }}
                      >
                        {header.isPlaceholder
                          ? null
                          : flexRender(
                              header.column.columnDef.header,
                              header.getContext(),
                            )}
                      </TableHead>
                    );
                  })}
                </TableRow>
              ))}
            </TableHeader>
            <TableBody>
              {table.getRowModel().rows?.length ? (
                table.getRowModel().rows.map((row) => (
                  <Drawer key={row.id} direction="right">
                    <DrawerTrigger asChild className="cursor-pointer">
                      <TableRow data-state={row.getIsSelected() && "selected"}>
                        {row.getVisibleCells().map((cell) => (
                          <TableCell
                            key={cell.id}
                            className="px-2"
                            style={{
                              width: cell.column.getSize(),
                              height: `${rowHeight}px`,
                            }}
                          >
                            {flexRender(
                              cell.column.columnDef.cell,
                              cell.getContext(),
                            )}
                          </TableCell>
                        ))}
                      </TableRow>
                    </DrawerTrigger>
                    <IssuesItem issue={row.original as Issue} />
                  </Drawer>
                ))
              ) : (
                <TableRow>
                  <TableCell
                    colSpan={columns.length}
                    className="h-full text-center"
                  >
                    No results.
                  </TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
        </div>
        <div className="flex w-full items-center justify-between gap-4">
          <div className="flex grow justify-end whitespace-nowrap text-muted-foreground text-sm">
            <p
              className="whitespace-nowrap text-muted-foreground text-sm"
              aria-live="polite"
            >
              <span className="text-foreground">
                {table.getState().pagination.pageIndex *
                  table.getState().pagination.pageSize +
                  1}
                -
                {Math.min(
                  Math.max(
                    table.getState().pagination.pageIndex *
                      table.getState().pagination.pageSize +
                      table.getState().pagination.pageSize,
                    0,
                  ),
                  table.getRowCount(),
                )}
              </span>{" "}
              of{" "}
              <span className="text-foreground">
                {table.getRowCount().toString()}
              </span>
            </p>
          </div>
          <div className="flex items-center gap-2">
            <Button
              size="icon"
              variant="outline"
              onClick={() => table.firstPage()}
              disabled={!table.getCanPreviousPage()}
            >
              <ChevronFirstIcon />
            </Button>
            <Button
              size="icon"
              variant="outline"
              onClick={() => table.previousPage()}
              disabled={!table.getCanPreviousPage()}
            >
              <ChevronLeftIcon />
            </Button>
            <Button
              size="icon"
              variant="outline"
              onClick={() => table.nextPage()}
              disabled={!table.getCanNextPage()}
            >
              <ChevronRightIcon />
            </Button>
            <Button
              size="icon"
              variant="outline"
              onClick={() => table.lastPage()}
              disabled={!table.getCanNextPage()}
            >
              <ChevronLastIcon />
            </Button>
          </div>
        </div>
      </div>
    </div>
  );
}
